
#include "f_gpio.h"
#include "f_gpio_hw.h"

void FGpioPinIrqMask(FGpio *instance_p, u32 pin)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_B_PIN0);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    /* set irq mask */
    val = FGPIO_READREG32(config_p->base_address, GPIO_INTMASK_OFFSET);
    val |= (1 << pin);
    FGPIO_WRITEREG32(config_p->base_address, GPIO_INTMASK_OFFSET, val);

    /* disable pin irq  */
    val = FGPIO_READREG32(config_p->base_address, GPIO_INTEN_OFFSET);
    val &= ~(1 << pin);
    FGPIO_WRITEREG32(config_p->base_address, GPIO_INTEN_OFFSET, val);
}

void FGpioPinIrqUnmask(FGpio *instance_p, u32 pin)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_B_PIN0);
    u32 val;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    /* clear irq mask */
    val = FGPIO_READREG32(config_p->base_address, GPIO_INTMASK_OFFSET);
    val &= ~(1 << pin);
    FGPIO_WRITEREG32(config_p->base_address, GPIO_INTMASK_OFFSET, val);

    /* enable pin irq  */
    val = FGPIO_READREG32(config_p->base_address, GPIO_INTEN_OFFSET);
    val |= (1 << pin);
    FGPIO_WRITEREG32(config_p->base_address, GPIO_INTEN_OFFSET, val);
}

void FGpioPinIrqSetType(FGpio *instance_p, u32 pin, FGpioIrqType type)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_B_PIN0);
    u32 level, polarity;
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    // read trriger and polarity
    level = FGPIO_READREG32(config_p->base_address, GPIO_INTTYPE_LEVEL_OFFSET);
    polarity = FGPIO_READREG32(config_p->base_address, GPIO_INT_POLARITY_OFFSET);

    switch (type)
    {
    case F_GPIO_IRQ_TYPE_EDGE_FALLING:
        level |= (1 << pin);
        polarity &= ~(1 << pin);
        break;
    case F_GPIO_IRQ_TYPE_EDGE_RISING:
        level |= (1 << pin);
        polarity |= (1 << pin);
        break;
    case F_GPIO_IRQ_TYPE_LEVEL_LOW:
        level &= ~(1 << pin);
        polarity &= ~(1 << pin);
        break;
    case F_GPIO_IRQ_TYPE_LEVEL_HIGH:
        level &= ~(1 << pin);
        polarity |= (1 << pin);
        break;
    default:
        return;
    }

    FGPIO_WRITEREG32(config_p->base_address, GPIO_INTTYPE_LEVEL_OFFSET, level);
    FGPIO_WRITEREG32(config_p->base_address, GPIO_INT_POLARITY_OFFSET, polarity);
}

void FGpioPinIrqAck(FGpio *instance_p, u32 pin)
{
    FT_ASSERTVOID(instance_p != NULL);
    FT_ASSERTVOID(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FT_ASSERTVOID(pin < F_GPIO_B_PIN0);
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    FGPIO_WRITEREG32(config_p->base_address, GPIO_PORTA_EOI_OFFSET, (1 << pin));
}

u32 FGpioPinIrqStatusGet(FGpio *instance_p)
{
    FT_ASSERTZERONUM(instance_p != NULL);
    FT_ASSERTZERONUM(instance_p->is_ready == FT_COMPONENT_IS_READY);
    FGpioConfig *config_p;
    config_p = &instance_p->config;

    return FGPIO_READREG32(config_p->base_address, GPIO_INTSTATUS_OFFSET);
}